package com.sunstar.androidmedia.meidahelper

import android.content.Context
import android.media.MediaCodec
import android.media.MediaCodecInfo
import android.media.MediaFormat
import android.media.MediaMuxer
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class MediaRecord(val imgHeight: Int, val imgWidth: Int, val context: Context) {
    private var mTracIndex: Int? = null
    private val codecName = MediaFormat.MIMETYPE_VIDEO_HEVC
    private val framerate = 30
    var isRecord = false
    var inputData: ByteArray? = null
    private var recordListener: MediaRecordListener? = null //录制监听

    private val outPutPath: String by lazy {
        context.cacheDir.path + "test.mp4"
    }

    private val mediaMuxer: MediaMuxer by lazy {
        val muxer = MediaMuxer(outPutPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
        muxer
    }
    private val mediaCodec by lazy {
        val codec = MediaCodec.createByCodecName(codecName)
        val format = MediaFormat.createVideoFormat(codecName, imgHeight, imgWidth)

        var bitrate = 2 * imgHeight * imgWidth * framerate;//码率

        format.run {
            setInteger(MediaFormat.KEY_BIT_RATE, bitrate)
            setInteger(MediaFormat.KEY_FRAME_RATE, framerate)
            setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2)
            setInteger(
                MediaFormat.KEY_COLOR_FORMAT,
                MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible
            )
        }
        codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
        codec
    }

    fun feedData(feedData: ByteArray) {
        inputData = feedData
    }

    /**
     * 结束录制
     *
     * */
    fun stopRecording() {
        isRecord = false
    }

    /**
     * 开始录制
     *
     * */
    fun startRecord() {
        mediaCodec.start()
        isRecord = true
        GlobalScope.launch(Dispatchers.IO) {
            while (isRecord) {
                val outPutBufs = mediaCodec.outputBuffers //拿到输出缓冲区,用于取到编码后的数据
                val inputBufs = mediaCodec.inputBuffers //拿到输入缓冲区,用于传送数据进行编码
                val inputBfIndex = mediaCodec.dequeueInputBuffer(-1)
                if (inputBfIndex >= 0) { //当输入缓冲区有效时,就是>=0
                    var inputBuffer = inputBufs[inputBfIndex]
                    inputBuffer.run {
                        clear()
                    }
                    inputData?.run {
                        //往输入缓冲区写入数据
                        inputBuffer.put(this)
                        //五个参数，第一个是输入缓冲区的索引，第二个数据是输入缓冲区起始索引，第三个是放入的数据大小，第四个是时间戳，保证递增就是
                        mediaCodec.queueInputBuffer(
                            inputBfIndex,
                            0,
                            this.size,
                            System.nanoTime() / 1000,
                            0
                        )
                    }

                }
                val bufferInfo = MediaCodec.BufferInfo()
                val outPutIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0)
                val outPutBuffer = mediaCodec.getOutputBuffer(outPutIndex)
                if (outPutIndex >= 0) {
                    val outBuffer = outPutBufs[outPutIndex]
                    val h264Byte = ByteArray(bufferInfo.size)
//                val h264Byte = outBuffer[outData]
                    outPutBuffer?.run {
                        // mediacodec的直接编码输出是h264
                        get(h264Byte)
                        position(bufferInfo.size)
                        limit(bufferInfo.offset + bufferInfo.size)
                        mTracIndex?.run {
                            mediaMuxer.writeSampleData(this, outPutBuffer, bufferInfo)
                        }
                        //释放缓冲区
                        mediaCodec.releaseOutputBuffer(outPutIndex, false)
                    }
                } else if (outPutIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                    val mediaFormat = mediaCodec.outputFormat
                    mTracIndex = mediaMuxer.addTrack(mediaFormat)
                    mediaMuxer.start()
                }

            }
            mediaCodec.run {
                stop()
                release()
            }
            mediaMuxer.run {
                stop()
                release()
            }
            GlobalScope.launch(Dispatchers.Main) {

            }
        }
    }

    interface MediaRecordListener {
        fun recordCompleted()
        fun recordStarted()
        fun recordIng()
    }
}
